package main

import (
	"fmt"
)

func main() {
	//切片的定义
	//语法：var关键字 变量名 []类型
	//长度可变，且长度不属于类型的一部分
	var a []string
	fmt.Printf("%T %v\n", a, a)
	//加上花括号就相当于声明的同时赋值了
	var b = []string{}
	fmt.Println(len(b))
	//可变长度，只能通过append追加的方式
	//因为append会出发切片的扩容
	//扩容逻辑是，替换一个新的底层数组，并把原来数组中的元素copy过来
	b = append(b, "b")
	fmt.Println(len(b))
	//用make声明切片、长度为3、容量为5
	//make专门用于三大引用类型的初始化，切片、map、chanel
	//容量就是，这个切片的底层数组的长度
	var c = make([]int, 3, 5)
	fmt.Println(c, len(c), cap(c))

	//切片的长度和容量
	//长度：元素个数
	//容量：切片指向底层数组的第一个元素，到底层数组最后一个元素的长度
	x := [8]int{0, 1, 2, 3, 4, 5, 6, 7}
	y := x[:5] //截取下标0-4
	fmt.Println(y, len(y), cap(y))
	z := x[3:6] //截取下标3-5
	fmt.Println(z, len(z), cap(z))
	q := z[:5] //z [3 4 5]
	fmt.Println(q, len(q), cap(q))

	//切片是引用类型，这里的slice2和slice指向相同的内存地址，slice2发生了变化，那么slice也会发生变化
	var slice = []int{1, 2, 3}
	slice2 := slice
	slice[0] = 10
	fmt.Println(slice, slice2)

	//append添加1个元素
	slice3 := []int{}          //底层是个空数组[0]int
	slice3 = append(slice3, 1) //换了个[2]int{1}的数组
	fmt.Println(cap(slice3))

	//append将切片合并
	slice4 := []int{10, 20, 30}
	slice5 := append(slice3, slice4...) //当追加的是个切片是，要加上...
	fmt.Println(slice5)

	//切片删除元素, 截取+合并的能力完成删除
	slice5 = append(slice5[:1], slice5[2:]...)
	fmt.Println(slice5)
}
